package com.yanqu.road.server.logic.season;

import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.rank.xrank.XSeasonUserRank;
import com.yanqu.road.entity.season.SeasonRewardConfig;
import com.yanqu.road.entity.season.SeasonRewardData;
import com.yanqu.road.entity.enums.eSeasonRewardType;
import com.yanqu.road.entity.season.SeasonRewardKey;
import com.yanqu.road.logic.helper.SeasonHelper;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.logic.xlogic.rank.season.XSeasonUserRankChangeParam;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.season.SeasonRewardModule;
import com.yanqu.road.server.logic.season.args.ReceiveSeasonRewardResult;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.cross3.GameXRankMgr;
import com.yanqu.road.server.manger.season.SeasonRewardMgr;
import com.yanqu.road.server.pb.PlayerPb;
import com.yanqu.road.server.protocol.GameErrorCode;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * zkt wait2 todo 待实现
 * 1. 榜单长度（SeasonHelper.getChannelSeasonMaxRank）
 * 2. 赛季结束全同步
 * 3. 玩家信息增量（XSeasonUserRankMap.userRankChange）（XRankPb.parseXUserRankMsg）
 */
public abstract class BaseSeasonRank extends BaseSeasonReward {

    protected String rangeKey;
    protected SeasonRewardData data;
    protected Map<Integer, SeasonRewardConfig> seasonRewardConfigMap;

    public BaseSeasonRank(eSeasonRewardType type, GamePlayer player) {
        super(type, player);

        this.rangeKey = initRangeKey();
        Optional<SeasonRewardData> first = player.getModule(SeasonRewardModule.class).getSeasonRewardDataMap(systemId, seasonId, type).values().stream().findFirst();
        this.data = first.isPresent() ? first.get() : null;
        this.seasonRewardConfigMap = SeasonRewardMgr.getSeasonRewardConfigMap(systemId, seasonId, type.getIntValue());
    }

    // ------------------------------------------------

    @Override
    public void handle(Object param) {

        if (data == null) {
            return;
        }
        Map<Integer, SeasonRewardConfig> configMap = SeasonRewardMgr.getSeasonRewardConfigMap(systemId, seasonId, type.getIntValue());
        if (configMap.isEmpty()) {
            return;
        }

        Map<Integer, SeasonRewardData> changeMap = new HashMap<>();
        if (!data.isGetReward() && canChange(param)) {
            changeValue(param);
            data.setTime(System.currentTimeMillis());
            changeMap.put(data.getRewardId(), data);

            if (canChangeRank()) {
                XSeasonUserRank userRank = new XSeasonUserRank();
                userRank.setSystemId(systemId);
                userRank.setSeasonId(seasonId);
                userRank.setConditionType(data.getType());
                userRank.setRangeKey(rangeKey);
                userRank.setChannelId(ServerListMgr.getChannelId(GameServer.getInstance().getServerId()));
                userRank.setServerId(GameServer.getInstance().getServerId());
                userRank.setUserId(player.getUserId());
                userRank.setBaseInfo(PlayerBasePb.parseToUserBaseInfo(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()).build()));
                userRank.setParam(data.getParam());
                userRank.setValue(BigInteger.valueOf(data.getValue()));
                userRank.setLastUpdateTime(System.currentTimeMillis());
                GameXRankMgr.getSeasonUserRankMap().userRankChange(userRank, new XSeasonUserRankChangeParam(true));
            }
        }
        player.getModule(SeasonRewardModule.class).addChangeData(changeMap);
    }

    public ReceiveSeasonRewardResult receiveSeasonRankReward(int myRank) {
        // 没到领奖时间
        int tmpRet = inGetRewardTime();
        if (tmpRet != 0) {
            return new ReceiveSeasonRewardResult(tmpRet);
        }
        // 没有玩家数据
        if (data == null) {
            return new ReceiveSeasonRewardResult(GameErrorCode.E_SEASON_REWARD_NO_COMPLETE);
        }
        // 已经领过奖
        if (data.isGetReward()) {
            return new ReceiveSeasonRewardResult(GameErrorCode.E_SEASON_REWARD_HAD_GET_REWARD);
        }
        // 拿排名奖励
        if (seasonRewardConfigMap == null || seasonRewardConfigMap.isEmpty()) {
            return new ReceiveSeasonRewardResult(GameErrorCode.E_SEASON_REWARD_TYPE_NO_EXIST);
        }
        SeasonRewardConfig myConfig = SeasonHelper.getRankRewardConfigByMyRank(seasonRewardConfigMap, myRank);
        if (myConfig == null) {
            return new ReceiveSeasonRewardResult(GameErrorCode.E_SEASON_REWARD_NO_COMPLETE);
        }

        // 设置领奖状态
        data.setGetReward(true);
        data.setTime(System.currentTimeMillis());

        Map<Integer, SeasonRewardData> changeMap = new HashMap<>();
        changeMap.put(data.getRewardId(), data);
        player.getModule(SeasonRewardModule.class).addChangeData(changeMap);

        // 加奖励
        player.getModule(CurrencyModule.class).addCurrency(myConfig.getReward(), eLogMoneyType.Season, eLogMoneyType.SeasonGetRankReward);

        return new ReceiveSeasonRewardResult(myConfig.getReward());
    }

    // ------------------------------------------------

    @Override
    protected boolean isComplete(SeasonRewardConfig config, SeasonRewardData data) {
        return false;
    }

    @Override
    protected boolean canChange(SeasonRewardConfig config, SeasonRewardData data, Object param) {
        return canChange(param);
    }

    @Override
    protected void changeValue(SeasonRewardConfig config, SeasonRewardData data, Object param) {
        changeValue(param);
    }

    @Override
    public ReceiveSeasonRewardResult receiveReward(SeasonRewardKey key, List<Integer> idList) {
        throw new RuntimeException("排行榜奖励不要用这个方法领奖");
    }

    protected abstract boolean canChange(Object param);

    protected abstract void changeValue(Object param);

    protected abstract String initRangeKey();

    public String getRangeKey() {
        return rangeKey;
    }

    public SeasonRewardData getData() {
        return data;
    }

    public abstract int inGetRewardTime();

    public boolean canChangeRank() {
        return true;
    }
}
